package com.ship.dispatch.controller.fob;

import cn.hutool.core.io.resource.InputStreamResource;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.ship.common.core.domain.R;
import com.ship.common.core.exception.BusException;
import com.ship.common.core.exception.ServiceException;
import com.ship.common.core.utils.DateUtils;
import com.ship.common.core.utils.FileUtils;
import com.ship.common.core.utils.HttpRequestUtil;
import com.ship.common.core.utils.StringUtils;
import com.ship.common.core.web.domain.BaseResultCode;
import com.ship.common.core.web.domain.JsonResult;
import com.ship.common.log.annotation.Log;
import com.ship.common.log.enums.BusinessType;
import com.ship.dispatch.annotation.DataChangeLog;
import com.ship.dispatch.bean.SpDispatchSchemeExecute;
import com.ship.dispatch.bean.SpFobSublease;
import com.ship.dispatch.bean.fob.*;
import com.ship.dispatch.bpm.service.TaskService;
import com.ship.dispatch.bpm.utils.TemplateParamUtils;
import com.ship.dispatch.bpm.vo.FileTemplaetDto;
import com.ship.dispatch.bpm.vo.ManageEntityVo;
import com.ship.dispatch.bpm.vo.RebackTaskVo;
import com.ship.dispatch.service.SpDispatchSchemeExecuteService;
import com.ship.dispatch.service.SpFobSubleaseService;
import com.ship.dispatch.service.fob.*;
import com.ship.system.api.RemoteFileService;
import com.ship.system.api.domain.SysFile;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.flowable.engine.HistoryService;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.scheduling.annotation.Async;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 *@title SpFobZzgcjrController
 *@description 船运执行业务处理通用接口
 *@author yl
 *@create 2023/12/13 0013
 */
//@Tag(name =  "管理后台 - 流程执行业务处理通用接口")
@Api(value = "fob", tags = "流程执行业务处理通用接口")
@RestController
@RequestMapping("/fob")
public class FobController {
    @Autowired
    FobService fobService;
    @Autowired
    SpFobFileRecordService spFobFileRecordService;

    @Autowired
    RecordService recordService;

    @Autowired
    SpFobJsfhccbItemsService spFobJsfhccbItemsService;

    @Autowired
    SpFobTemplateService spFobTemplateService;

    @Autowired
    private RemoteFileService remoteFileService;

    @Autowired
    @Lazy
    SpDispatchSchemeExecuteService spDispatchSchemeExecuteService;

    @Value("${file_server.host}")
    private String fileServerHost;
    private static final String FILE_UPLOAD_PATH = "/group1/upload";
    /**
     * 船运执行业务处理通用接口 新增 / 修改 / 完成任务
     * @param manageEntityVo
     * @return
     */
    @DataChangeLog(type="update")
    @PostMapping("/manage")
    public JsonResult manage(HttpServletRequest request, @RequestBody @Validated ManageEntityVo manageEntityVo){
        return fobService.manage(manageEntityVo);
    }

    /**
     * 单独完成任务
     * @param manageEntityVo
     * @return
     */
    @PostMapping("/completeTask")
    @Log(title = "单独完成任务",businessType = BusinessType.OTHER)
    public JsonResult completeTask(@RequestBody @Validated ManageEntityVo manageEntityVo) throws IOException {
        return fobService.completeTask(manageEntityVo);
    }

    /**
     * 船运执行 订单开启审批操作
     * @param serviceId
     * @param key
     * @return
     */
    @GetMapping("/startApprovalProcess/{serviceId}/{key}")
    public JsonResult startApprovalProcess(@PathVariable("serviceId") Long serviceId,@PathVariable("key") String key){
        fobService.startApprovalProcess(serviceId,key);
        return JsonResult.success();
    }

    /**
     * 撤回任务
     * @param rebackTaskVo
     * @return
     */
    @PostMapping("/rebackTask")
    @Log(title = "撤回任务",businessType = BusinessType.OTHER)
    public JsonResult rebackTask(@RequestBody RebackTaskVo rebackTaskVo){
        return fobService.rebackTask(rebackTaskVo);
    }

    /**
     * 复制多倍表单执行
     * @param addFromVo
     * @return
     */
    @PostMapping("/addForm")
    @Log(title = "复制多表单执行",businessType = BusinessType.OTHER)
    public JsonResult addForm(@RequestBody RebackTaskVo addFromVo){
        return fobService.addForm(addFromVo);
    }


    /**
     * 船运执行获取业务表单数据
     * @param key 根据业务类型
     * @param id 业务id
     * @return
     */
    @Log
    @GetMapping("/get/{key}/{id}/{serviceId}")
    public JsonResult get(@PathVariable("key") String key,@PathVariable("id") String id,@PathVariable("serviceId") Long serviceId,HttpServletRequest request){
        if(serviceId==-1){
            serviceId = null;
        }
        return fobService.getServiceFormData(key,id,serviceId);
    }
    @DeleteMapping("/deleteFile/{id}")
    @Log(title = "删除文件",businessType = BusinessType.DELETE)
    public JsonResult deleteFile(@PathVariable("id") Long id){
        spFobFileRecordService.removeById(id);
        return JsonResult.success();
    }
    @PostMapping("/get/template")
    public JsonResult getTemplateInfo(@RequestBody ManageEntityVo manageEntityVo){
        return fobService.getTemplateInfo(manageEntityVo);
    }

    @GetMapping("/get/emailTemplate/{templateId}/{pocessInstanceId}")
    public JsonResult getEmailTemplateInfo(@PathVariable("templateId") Long templateId,@PathVariable("pocessInstanceId") String pocessInstanceId){
        if(templateId==null){
            return JsonResult.success("");
        }
        return fobService.getEmailTemplateInfo(templateId,pocessInstanceId);
    }


    @PostMapping("/upload")
    @Log(title = "上传文件",businessType = BusinessType.IMPORT)
    public JsonResult upload(@RequestParam(value = "file",required = false) MultipartFile file,
                             @RequestParam("schemeDetailId") String schemeDetailId,
                             @RequestParam("processInstanceId") String processInstanceId,
                             @RequestParam("key") String key,
                             @RequestParam("serviceId") String serviceId
    ){
        FileUtils.checkFileName(file);
        try {
            String fileType = fobService.getFileTypeByNodeKey(key);
            //Flux<DataBuffer> bufferFlux = file.content();
            String name = file.getOriginalFilename();
            String url = "";

            url = upload(file);
            //新增删除临时文件  通常位于tmp目录下
            //file.delete().subscribe();
            SpFobFileRecord spFobFileRecord = new SpFobFileRecord();
            spFobFileRecord.setPath(url);
            spFobFileRecord.setName(name);
            spFobFileRecord.setProceeInstanceId(processInstanceId);
            spFobFileRecord.setFileType(fileType);
            spFobFileRecord.setNode(key);
            spFobFileRecord.setSchemeDetailId(Long.parseLong(schemeDetailId));
            spFobFileRecord.setServiceId(Long.parseLong(serviceId));
            spFobFileRecordService.save(spFobFileRecord);

            Map<String,String> map = new HashMap<>();
            map.put("id",spFobFileRecord.getId()+"");
            map.put("path",spFobFileRecord.getPath());
           // Long id = spFobFileRecord.getId();
            return JsonResult.success(map);
        }catch (Exception e){
            e.printStackTrace();
            throw new BusException("文件服务器连接失败",BaseResultCode.GENERAL_ERROR);
        }
    }

    @Resource
    HttpRequestUtil httpRequestUtil;
    @PostMapping("/upload2")
    @Log(title = "上传文件",businessType = BusinessType.IMPORT)
    public JsonResult upload2(@RequestParam(value = "file",required = false) MultipartFile file
    ){
        FileUtils.checkFileName(file);
        try {
            JSONObject jsonObject =  httpRequestUtil.updateocr(file);
            return JsonResult.success(jsonObject);
        }catch (Exception e){
            e.printStackTrace();
            throw new BusException("文件服务器连接失败",BaseResultCode.GENERAL_ERROR);
        }
    }

    @Autowired
    SpFobLabelItemService spFobLabelItemService;
    /**
     * flux 为响应式编程
     * 船运执行文件上传注入参数生成模板信息
     * @param file
     * @param schemeDetailId
     * @param key
     * @param serviceId
     * @return
     */
    @Async
    @PostMapping("/updateTemplate")
    @Log(title = "更新模板",businessType = BusinessType.UPDATE)
    public JsonResult updateTemplate(@RequestPart(value = "file", required = false) FilePart file,
                             @RequestPart("schemeDetailId") String schemeDetailId,
                             @RequestPart("processInstanceId") String processInstanceId,
                             @RequestPart("key") String key,
                             @RequestPart("serviceId") String serviceId
    ){

        try {
            String fileType = fobService.getFileTypeByNodeKey(key);
            Flux<DataBuffer> bufferFlux = file.content();
            String name = file.filename();
            if(!name.contains(".docx")){
                return JsonResult.failed("文件格式不匹配，请上传.docx类型文件");
            }
            Mono<SpFobFileRecord> mono = bufferFlux.map(dataBuffer->dataBuffer.asInputStream()).reduce(SequenceInputStream::new).flatMap(
                    inputStream -> {
                        String url = "";
                        try {
                            ByteArrayOutputStream tempoutputStream = new ByteArrayOutputStream();
                            byte[] buffer = new byte[1024];
                            int len;
                            while ((len = inputStream.read(buffer)) > -1) {
                                tempoutputStream.write(buffer, 0, len);
                            }
                            InputStream in1 = new ByteArrayInputStream(tempoutputStream.toByteArray());
                            XWPFDocument doc = new XWPFDocument(in1);
                            // 创建文本提取器
                            XWPFWordExtractor extractor = new XWPFWordExtractor(doc);
                            // 提取文本内容
                            String text = extractor.getText();

//                            // 打印文本内容
//                            System.out.println(text);
                            // 关闭文档
                            doc.close();
                            List<String> labels = new ArrayList<>();
                            // 解析文档中标签数据
                            labels = TemplateParamUtils.templateLabel(text,labels);
                            // 处理 获取数据逻辑
                            Map<String,String> labelResult = spFobLabelItemService.getLabelKesData("",labels,processInstanceId);
                            //Configure.ConfigureBuilder builder = Configure.newBuilder();
                            ConfigureBuilder builder = Configure.newBuilder();
                            InputStream in2 = new ByteArrayInputStream(tempoutputStream.toByteArray());
                            XWPFTemplate template = XWPFTemplate.compile(in2,builder.buildGramer("<!","!>").build()).render(labelResult);
                            OutputStream outputStream = new FileOutputStream(name);
                            template.write(outputStream);
                            template.close();
                            outputStream.close();
                            tempoutputStream.close();
                            FileInputStream fileInputStream = new FileInputStream(name);
                            ByteArrayOutputStream out = new ByteArrayOutputStream();
                            byte[] buffer2 = new byte[1024];
                            int len2;
                            while ((len2 = fileInputStream.read(buffer2)) > -1) {
                                out.write(buffer2, 0, len2);
                            }
                            fileInputStream.close();
                            InputStream byteArrayInputStream = new ByteArrayInputStream(out.toByteArray());
                            MultipartFile multipartFile = new MockMultipartFile("file", name, "application/octet-stream", byteArrayInputStream);
                            R<SysFile> result1 = remoteFileService.upload(multipartFile);
                            if(result1.getCode() != R.SUCCESS){
                                throw new BusException("文件服务器连接失败", BaseResultCode.GENERAL_ERROR);
                            }
                            url = result1.getData().getHttpsUrl();
                            file.delete().subscribe();
                            SpFobFileRecord spFobFileRecord = new SpFobFileRecord();
                            spFobFileRecord.setPath(url);
                            spFobFileRecord.setName(name);
                            spFobFileRecord.setProceeInstanceId(processInstanceId);
                            spFobFileRecord.setFileType(fileType);
                            spFobFileRecord.setNode(key);
                            spFobFileRecord.setSchemeDetailId(Long.parseLong(schemeDetailId));
                            spFobFileRecord.setServiceId(Long.parseLong(serviceId));
                            spFobFileRecordService.save(spFobFileRecord);
                            return Mono.justOrEmpty(spFobFileRecord);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        return null;
                    }
            );
            return JsonResult.success(mono.block());
        }catch (Exception e){
            throw new BusException("文件服务器连接失败",BaseResultCode.GENERAL_ERROR);
        }
    }

    @PostMapping("/updateFileTemplate")
    @Log(title = "更新文件模板",businessType = BusinessType.UPDATE)
    public JsonResult updateFileTemplate(@RequestBody FileTemplaetDto dto){
        if(dto.getTemplateId()==null){
            return JsonResult.success(new SpFobFileRecord());
        }
        SpFobTemplate fobTemplate = spFobTemplateService.getById(dto.getTemplateId());
        if(fobTemplate==null){
            return JsonResult.failed("模板不存在，请重新选择确认");
        }
        try {
            SpFobBaseBean spFobBaseBean = fobService.getSpFobBaseBean(dto.getKey(),dto.getProcessInstanceId());
            //已完成任务不再更新文件模版
            List<SpFobFileRecord> records = spFobFileRecordService.list(new LambdaQueryWrapper<SpFobFileRecord>().eq(SpFobFileRecord::getServiceId,dto.getServiceId()).isNotNull(SpFobFileRecord::getTemplateId).eq(SpFobFileRecord::getOrderDetailId,dto.getTemplateId()).orderByDesc(SpFobFileRecord::getCreateDate));
            if(records.size()>0){
                return JsonResult.success(records.get(0));
            }
            String fileType = fobService.getFileTypeByNodeKey(dto.getKey());
            //Path path = Paths.get(fobTemplate.getContent());
            File file = new File(fobTemplate.getContent());
            String name = URLDecoder.decode(file.getName(), "UTF-8");
            file.delete();
//            URL httpUrl = new URL(fobTemplate.getContent());
//            InputStream inputStream = httpUrl.openConnection().getInputStream();
            String encodedFilePath = fobTemplate.getContent().replace(" ", "%20");
//            String oldPart = "http://10.75.33.149:9300/statics";
//            String newPart = "https://lngshipping.cgp.cnooc/api/file/statics";
//
//            //String newUrl = encodedFilePath;
//            if (encodedFilePath.contains("https://lngshipping.cgp.cnooc")) {
//                encodedFilePath = encodedFilePath.replace(newPart, oldPart);
//            }
            String CsoldPart = "http://10.75.34.224:9300/statics";
            String ZsoldPart = "http://10.75.33.149:9300/statics";
            String CsPart = "https://lngshippingcs.cgp.cnooc/api/file/statics";
            String ZsPart = "https://lngshipping.cgp.cnooc/api/file/statics";

            String newUrl = "";
            if (encodedFilePath.contains("https://lngshipping.cgp.cnooc")) {
                newUrl = encodedFilePath.replace(ZsPart, ZsoldPart);
            } else if (encodedFilePath.contains("https://lngshippingcs.cgp.cnooc")) {
                newUrl = encodedFilePath.replace(CsPart, CsoldPart);
            } else {
                newUrl = encodedFilePath;
            }
            //String httpUri = newUrl;
            URI httpUrl = new URI(newUrl);
            URL uri = httpUrl.toURL();
            InputStream inputStream = uri.openConnection().getInputStream();
            ByteArrayOutputStream tempoutputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) > -1) {
                tempoutputStream.write(buffer, 0, len);
            }
            InputStream in1 = new ByteArrayInputStream(tempoutputStream.toByteArray());
            XWPFDocument doc = new XWPFDocument(in1);
            // 创建文本提取器
            XWPFWordExtractor extractor = new XWPFWordExtractor(doc);
            // 提取文本内容
            String text = extractor.getText();

            // 打印文本内容
//            System.out.println(text);
            // 关闭文档
            doc.close();
            List<String> labels = new ArrayList<>();
            // 解析文档中标签数据
            labels = TemplateParamUtils.templateLabel(text, labels);
            if (labels == null || labels.size() == 0) {
                SpFobFileRecord spFobFileRecord = new SpFobFileRecord();
                spFobFileRecord.setPath(fobTemplate.getContent());
                spFobFileRecord.setName(name);
                spFobFileRecord.setProceeInstanceId(dto.getProcessInstanceId());
                spFobFileRecord.setFileType(fileType);
                spFobFileRecord.setNode(dto.getKey());
                spFobFileRecord.setSchemeDetailId(dto.getSchemeDetailId());
                spFobFileRecord.setServiceId(dto.getServiceId());
                spFobFileRecord.setTemplateId(dto.getTemplateId());
                spFobFileRecordService.save(spFobFileRecord);
                return JsonResult.success(spFobFileRecord);
            }
            // 处理 获取数据逻辑
            String nodeKey = fobTemplate.getTemplateKey();
            //nodeKey =nodeKey.substring(0,nodeKey.lastIndexOf("-"));
            Map<String, String> labelResult = spFobLabelItemService.getLabelKesData(nodeKey, labels, dto.getProcessInstanceId());
            ConfigureBuilder builder = Configure.newBuilder();
            InputStream in2 = new ByteArrayInputStream(tempoutputStream.toByteArray());
//            XWPFTemplate template = XWPFTemplate.compile(in2,builder.buildGramer(TemplateParamUtils.DYNAMIC_PARAM_PREFIX2,TemplateParamUtils.DYNAMIC_PARAM_SUFFIX2).build()).render(labelResult);
            XWPFTemplate template;
            try {
                template = XWPFTemplate.compile(in2, builder.buildGramer(TemplateParamUtils.DYNAMIC_PARAM_PREFIX2, TemplateParamUtils.DYNAMIC_PARAM_SUFFIX2).build()).render(labelResult);
            } catch (IndexOutOfBoundsException e) {
                System.out.println("解析失败，检查占位符及对应数据。labelResult内容: " + labelResult);
                e.printStackTrace();
                throw e;
            }
            SpFobSublease spFobSublease = spFobSubleaseService.getExceuteByInstanceId(dto.getProcessInstanceId());
            String newName = UUID.randomUUID() + "-" + name + ".docx";
            if(spFobSublease!=null){
                newName = "商务执行：" +spFobSublease.getShipName()+ "-" + name + ".docx";
            }else {
                SpDispatchSchemeExecute spDispatchSchemeExecute = spDispatchSchemeExecuteService.getExceuteByInstanceId(dto.getProcessInstanceId());
                if(spDispatchSchemeExecute!=null){
                    newName = "船运执行：" +spDispatchSchemeExecute.getVoyageNo()+ "-" + name + ".docx";
                }
            }
            //String newName = UUID.randomUUID() + "-" + name + ".docx";
            OutputStream outputStream = new FileOutputStream(newName);
            template.write(outputStream);
            template.close();
            outputStream.close();
            tempoutputStream.close();
            FileInputStream fileInputStream = new FileInputStream(newName);
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buffer2 = new byte[1024];
            int len2;
            while ((len2 = fileInputStream.read(buffer2)) > -1) {
                out.write(buffer2, 0, len2);
            }
            fileInputStream.close();

            InputStream byteArrayInputStream = new ByteArrayInputStream(out.toByteArray());
            //String url = upload(byteArrayInputStream,name);
            MultipartFile multipartFile = new MockMultipartFile("file", UUID.randomUUID() + "-" + name, "application/octet-stream", byteArrayInputStream);
            R<SysFile> result1 = remoteFileService.upload(multipartFile);
            if (result1.getCode() != R.SUCCESS) {
                throw new BusException("文件服务器连接失败", BaseResultCode.GENERAL_ERROR);
            }
            // 删除可能存在的临时文件
            try {
                File newFile = new File(multipartFile.getOriginalFilename());
                if (newFile.exists()) {
                    newFile.delete();
                }
                File newTempFile = new File(newName);
                if (newTempFile.exists()) {
                    newTempFile.delete();
                }
            } catch (Exception e) {
            }
            String url = result1.getData().getHttpsUrl();
            SpFobFileRecord spFobFileRecord = new SpFobFileRecord();
            spFobFileRecord.setPath(url);
            spFobFileRecord.setName(name);
            spFobFileRecord.setProceeInstanceId(dto.getProcessInstanceId());
            spFobFileRecord.setFileType(fileType);
            spFobFileRecord.setNode(dto.getKey());
            spFobFileRecord.setSchemeDetailId(dto.getSchemeDetailId());
            spFobFileRecord.setServiceId(dto.getServiceId());
            spFobFileRecord.setTemplateId(dto.getTemplateId());
            spFobFileRecordService.save(spFobFileRecord);
            return JsonResult.success(spFobFileRecord);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
        return JsonResult.failed("解析模板失败");
    }

    /**
     * 上传附件M
     * @return
     */
    public String upload(InputStream inputStream,String name){
        String result = "";
        try {
            InputStreamResource isr = new InputStreamResource(inputStream,
                    name);

            Map<String, Object> params = new HashMap<>();
            params.put("file", isr);
            //params.put("path", "86501729");
            params.put("output", "json");
            /*params.put("auth_token", "123");*/
            String resp = HttpRequest.post("http://106.12.241.246:9300" + FILE_UPLOAD_PATH).form(params).timeout(-1).execute().body();
            //String resp = HttpUtil.post(fileServerHost + FILE_UPLOAD_PATH, params);
            JSONObject re = JSONObject.parseObject(resp);
            if(!re.getString("retcode").equals("0")){
                throw new BusException(re.getString("retmsg"),BaseResultCode.GENERAL_ERROR);
            }
            result = re.getString("domain") + re.getString("path");
        } catch (Exception e) {
            throw new BusException("文件服务器连接失败",BaseResultCode.GENERAL_ERROR);
        }
        return result;
    }

    @ApiOperation(value = "获取文件模版生成后地址 templateId 模版id ,serviceId 业务ID")
    @GetMapping("/getFileTemplateUrl/{templateId}/{serviceId}")
    public JsonResult getFileTemplateUrl(@PathVariable("templateId") Long templateId,@PathVariable("serviceId")Long serviceId){
        List<SpFobFileRecord> records = spFobFileRecordService.list(new LambdaQueryWrapper<SpFobFileRecord>().eq(SpFobFileRecord::getTemplateId,templateId).eq(SpFobFileRecord::getServiceId,serviceId).orderByDesc(SpFobFileRecord::getCreateDate));
        if(records.size()>0){
            return JsonResult.success(records.get(0));
        }
        return JsonResult.success();
    }




        /**
         * 上传附件M
         * @return
         */
    public String upload(MultipartFile file){
        FileUtils.checkFileName(file);
        R<SysFile> result1 = remoteFileService.upload(file);
        if(result1.getCode() != R.SUCCESS){
            throw new BusException("文件服务器连接失败", BaseResultCode.GENERAL_ERROR);
        }
        String result = result1.getData().getHttpsUrl();;
        return result;
    }

    /**
     * 根据调度方案id 获取船运执行基础信息页面接口
     * @param processInstanceId
     * @return
     */
    @GetMapping("/baseInfo/{processInstanceId}")
    public JsonResult fobBaseInfo(@PathVariable("processInstanceId") String processInstanceId){
        return fobService.getFobBaseInfo(processInstanceId);
    }

    /**
     * 文件拓扑查询接口
     * @param processInstanceId
     * @return
     */
    @GetMapping("/file/record/{processInstanceId}")
    public JsonResult findFileRecord(@PathVariable("processInstanceId") String processInstanceId){
        List<SpFobFileRecord>  crons = fobService.getBaseCronInfo(processInstanceId);
        List<SpFobFileRecord> spFobFileRecordList = spFobFileRecordService.list(new LambdaQueryWrapper<SpFobFileRecord>().eq(SpFobFileRecord::getProceeInstanceId,processInstanceId).eq(SpFobFileRecord::getIsDelete,1));
        if(CollectionUtils.isNotEmpty(spFobFileRecordList)){
            crons.addAll(spFobFileRecordList);
        }
        return JsonResult.success(crons);
    }

    @GetMapping("/datachange/record/{processInstanceId}")
    public JsonResult findDataChangeRecord(@PathVariable("processInstanceId") String processInstanceId){
        List<Record> records = recordService.list(new LambdaQueryWrapper<Record>().eq(Record::getProceeInstanceId,processInstanceId).orderByDesc(Record::getCreateDate));
        return JsonResult.success(records);
    }

    /**
     * 获取报关费用信息详情
     * @param costId
     * @return
     */
    @GetMapping("/cost/info/{costId}/{processInstanceId}/{key}")
    public JsonResult getBgCostInfo(@PathVariable("costId") Long costId,@PathVariable("processInstanceId") String processInstanceId,@PathVariable("key") String key){
        return spFobJsfhccbItemsService.getBgCostInfo(costId,processInstanceId,key);
    }

    /**
     * 获取交还船结算详情
     * @param costId
     * @param processInstanceId
     * @param key
     * @return
     */
    @GetMapping("/instructions/info/{costId}/{processInstanceId}/{key}")
    public JsonResult getInstructionsInfo(@PathVariable("costId") Long costId,@PathVariable("processInstanceId") String processInstanceId,@PathVariable("key") String key){
        return spFobJsfhccbItemsService.getInstructionsInfo(costId,processInstanceId,key);
    }

    /**
     * 保存报关费用明细
     * @return
     */
    @PostMapping("/cost/save")
    @Log(title = "保存报关费用明细",businessType = BusinessType.INSERT)
    public JsonResult saveBgCostInfo(@RequestBody List<SpFobJsfhccbItems> spFobJsfhccbItems){
        return spFobJsfhccbItemsService.saveBgCostInfo(spFobJsfhccbItems);
    }
    @GetMapping("/getDeliveryDate/info/{processInstanceId}/{type}/{unit}")
    @ApiOperation(value = "获取交还船更新时间 type 0 交船 1 还船 unit（时间格式） 0 UTC 1 LT")
    public JsonResult getDeliveryDate(@PathVariable("processInstanceId") String processInstanceId,@PathVariable("type") Integer type,@PathVariable("unit") Integer unit){
        return spFobJsfhccbItemsService.getDeliveryDate(processInstanceId,type,unit);
    }

    @Autowired
    @Lazy
    TaskService taskService;

    @ApiOperation(value = "生成附件压缩包 file 表格文件，costId 计量ID，key 流程节点key")
    @PostMapping("/down/zip")
    public JsonResult downzip(@RequestParam(value = "file",required = false) MultipartFile file,@RequestParam(value = "costId") Long costId,@RequestParam(value = "key") String key,@RequestParam(value = "processInstanceId") String processInstanceId){
        FileUtils.checkFileName(file);
        List<SpFobJsfhccbItems> items = spFobJsfhccbItemsService.list(new LambdaQueryWrapper<SpFobJsfhccbItems>().eq(SpFobJsfhccbItems::getJsfhccbId,costId));
        List<String> fileId = new ArrayList<>();
        String shipName = "";
        SpFobSublease spFobSublease = spFobSubleaseService.getExceuteByInstanceId(processInstanceId);
        if(spFobSublease!=null){
           shipName = spFobSublease.getShipName();
        }else {
            SpDispatchSchemeExecute execute =  spDispatchSchemeExecuteService.getExceuteByInstanceId(processInstanceId);
            if(execute!=null){
                shipName = execute.getShipName();
            }
        }
        for(SpFobJsfhccbItems item:items){
            if("upload".equals(item.getA5Type()) && StringUtils.isNotEmpty(item.getA5())){
                String[] ids = item.getA5().split(",");
                Collections.addAll(fileId, ids);
            }
            if("upload".equals(item.getA6Type()) && StringUtils.isNotEmpty(item.getA6())){
                String[] ids = item.getA6().split(",");
                Collections.addAll(fileId, ids);
            }
        }
        String taskName = taskService.getNodeNameByKey(key);
        String zipFileName = "";
        String excelFileName = "";
        String timeStr = DateUtils.getTime();
        if(StringUtils.isNotEmpty(shipName)){
            zipFileName = shipName+"-"+taskName+"-"+timeStr+".zip";
            excelFileName = shipName+"-"+taskName+"-"+timeStr+".xlsx";
        }else{
            zipFileName = taskName +"-"+timeStr+".zip";
            excelFileName = taskName +"-"+timeStr+".xlsx";
        }
        String downUrl = "";
        List<SpFobFileRecord> records = new ArrayList<>();
        if(fileId!=null || fileId.size()>0){
            try{
                records = spFobFileRecordService.listByIds(fileId);
            }catch (Exception e){
            }
        }
        if((records!=null && records.size()>0) || file!=null){
            List<String> urls = (records!=null && records.size()>0)?records.stream().map(SpFobFileRecord::getPath).collect(Collectors.toList()):new ArrayList<>();
            try{
                if(file!=null){
                    urls.add("-1");
                }
                if(urls!=null && urls.size()>0){
                    compressFiles(urls,zipFileName,file,excelFileName);
                    File tempFile = new File(zipFileName);
                    MultipartFile multipartFile = convertFileToMultipartFile(tempFile);
                    R<SysFile> result1 = remoteFileService.upload(multipartFile);
                    if(result1.getCode() != R.SUCCESS){
                        throw new BusException("文件服务器连接失败", BaseResultCode.GENERAL_ERROR);
                    }
                    tempFile.delete();
                    downUrl = result1.getData().getHttpsUrl();
                }
            }catch (Exception e){
                return JsonResult.failed(e.getMessage());
            }
        }
        return JsonResult.success(downUrl);
    }


    @Autowired
    SpFobSubleaseService spFobSubleaseService;
    @ApiOperation(value = "获取船运执行记录 船运执行审批记录调整 serviceType serviceId")
    @GetMapping("/schemeExecute/info/{serviceType}/{serviceId}")
    public JsonResult getSchemeExecute(@PathVariable("serviceType") String serviceType,@PathVariable("serviceId") Long serviceId){
       String processInstanceId =  fobService.getExecuteInstance(serviceType,serviceId);
       if(processInstanceId!=null){
           SpDispatchSchemeExecute execute = spDispatchSchemeExecuteService.getExceuteByInstanceId(processInstanceId);
           if(execute==null){
               SpFobSublease spFobSublease = spFobSubleaseService.getExceuteByInstanceId(processInstanceId);
               return JsonResult.success(spFobSublease);
           }
           return JsonResult.success(execute);
       }
       return JsonResult.failed("获取船运执行信息失败");
    }

    @GetMapping("/getTaskFormData/info/{serviceType}/{serviceId}")
    public JsonResult getTaskFormData(@PathVariable("serviceType") String serviceType,@PathVariable("serviceId") Long serviceId){
        return taskService.getTaskFormData(serviceType,serviceId);
    }
    /**
     * 压缩文件
     * @param filePaths
     * @param zipFileName
     * @throws IOException
     */
    public static void compressFiles(List<String> filePaths, String zipFileName,MultipartFile execl,String excelName) throws IOException, URISyntaxException {
        try (
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(zipFileName));
                ZipOutputStream zipOut = new ZipOutputStream(bos)
        ) {
            int i=0;
            for (String filePath : filePaths) {
                i++;
                if("-1".equals(filePath)){
                    //File templfile = convert(execl);
                    //String name = URLDecoder.decode(execl.getOriginalFilename(), "UTF-8");
                    //templfile.delete();
                    //InputStream inputStream = execl.getInputStream();// uri.openConnection().getInputStream();
                    InputStream inputStream = execl.getInputStream();
                    File file = new File(excelName);
                    saveToFile(inputStream,file);
                    try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file))) {
                        ZipEntry entry = new ZipEntry(file.getName());
                        zipOut.putNextEntry(entry);
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = in.read(buffer)) != -1) {
                            zipOut.write(buffer, 0, len);
                        }
                    }
                    file.delete();
                }else{
                    File templfile = new File(filePath);
                    String name = URLDecoder.decode(templfile.getName(), "UTF-8");
                    templfile.delete();
                    String encodedFilePath = filePath.replace(" ", "%20");
                    String oldPart = "http://10.75.33.149:9300/statics";
                    String newPart = "https://lngshipping.cgp.cnooc/api/file/statics";

                    //String newUrl = encodedFilePath;
                    if (encodedFilePath.contains("https://lngshipping.cgp.cnooc")) {
                        encodedFilePath = encodedFilePath.replace(newPart, oldPart);
                    }
                    URI httpUrl = new URI(encodedFilePath);
                    URL uri = httpUrl.toURL();
                    InputStream inputStream = uri.openConnection().getInputStream();
                    File file = new File("附件"+i+":"+name);
                    saveToFile(inputStream,file);
                    try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file))) {
                        ZipEntry entry = new ZipEntry(file.getName());
                        zipOut.putNextEntry(entry);
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = in.read(buffer)) != -1) {
                            zipOut.write(buffer, 0, len);
                        }
                    }
                    file.delete();
                }
            }
        }
    }

    public static MultipartFile convertFileToMultipartFile(File file) throws IOException {
        FileInputStream input = new FileInputStream(file);
        MultipartFile multipartFile = new MockMultipartFile("file",
                file.getName(), "application/octet-stream", input);
        return multipartFile;
    }

    public static File convert(MultipartFile multipartFile) throws IOException {
        // 获取文件的临时路径
        String tempPath = multipartFile.getOriginalFilename();
        // 使用Files类创建临时文件
        Path path = Files.createTempFile(Paths.get(tempPath), "prefix", "suffix");
        // 获取临时文件
        File tempFile = path.toFile();
        // 将MultipartFile的内容复制到临时文件中
        multipartFile.transferTo(tempFile);
        return tempFile;
    }
    public static void saveToFile(InputStream inputStream, File outputFile) throws IOException {
        if (outputFile.exists()) {
            outputFile.delete();
        }
        try (OutputStream outputStream = new FileOutputStream(outputFile)) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        }
    }


    public static void main(String[] args) throws IOException {
        File file = new File("78c953d7-6ae2-4bd3-b166-e9b3b1c469e1-test.docx");
        Map<String,String> labelResult = new HashMap<>();
        labelResult.put("商务执行_船东","测试222");
        labelResult.put("商务执行","是");
        ConfigureBuilder builder = Configure.newBuilder();
        InputStream in = null;
        try {
            in = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
        //InputStream in2 = new FileInputStream(file).   ;
        XWPFTemplate template = XWPFTemplate.compile(in,builder.buildGramer(TemplateParamUtils.DYNAMIC_PARAM_PREFIX2,TemplateParamUtils.DYNAMIC_PARAM_SUFFIX2).build()) .render(labelResult);
        String newName = UUID.randomUUID()+"-test2.docx";
        OutputStream outputStream = new FileOutputStream(newName);
        template.write(outputStream);
        template.close();
        outputStream.close();
        //tempoutputStream.close();
    }

}
